using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SpaceWolf.GameLogic
{
    public enum EconomyType{Rich_Industrial,
                        Average_Industrial,
						Poor_Industrial,
						Mainly_Industrial,
						Mainly_Agricultural,
						Rich_Agricultural,
						Average_Agricultural,
						Poor_Agricultural};

    public enum GovernmentType{Anarchy,
							Feudal,
							Multi_Government,
							Dictatorship,
							Communist,
							Confederacy,
							Democracy,
							Corporate_State};

    public struct planet_data
    {
        public GovernmentType government;
        public EconomyType economy;
        public int techlevel;
        public int population;
        public int productivity;
        public int radius;
    };
    
    public struct galaxy_seed
    {
        public byte a;	/* 6c */
        public byte b;	/* 6d */
        public byte c;	/* 6e */
        public byte d;	/* 6f */
        public byte e;	/* 70 */
        public byte f;	/* 71 */

        public galaxy_seed(byte a, byte b, byte c, byte d, byte e, byte f)
        {
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
            this.e = e;
            this.f = f;
        }
    };

    public struct random_seed
    {
        public int a;
        public int b;
        public int c;
        public int d;
    };

    public class Planet
    {
        #region Variables
        random_seed rnd_seed;

        string planet_description = string.Empty;

        string[,] desc_list =new string[36,5]{
/*  0	*/	{"fabled", "notable", "well known", "famous", "noted"},
/*  1	*/	{"very", "mildly", "most", "reasonably", ""},
/*  2	*/	{"ancient", "<20>", "great", "vast", "pink"},
/*  3	*/	{"<29> <28> plantations", "mountains", "<27>", "<19> forests", "oceans"},
/*  4	*/	{"shyness", "silliness", "mating traditions", "loathing of <5>", "love for <5>"},
/*  5	*/	{"food blenders", "tourists", "poetry", "discos", "<13>"},
/*  6	*/	{"talking tree", "crab", "bat", "lobst", "%R"},
/*  7	*/	{"beset", "plagued", "ravaged", "cursed", "scourged"},
/*  8	*/	{"<21> civil war", "<26> <23> <24>s", "a <26> disease", "<21> earthquakes", "<21> solar activity"},
/*  9	*/	{"its <2> <3>", "the %I <23> <24>","its inhabitants' <25> <4>", "<32>", "its <12> <13>"},
/* 10	*/	{"juice", "brandy", "water", "brew", "gargle blasters"},
/* 11	*/	{"%R", "%I <24>", "%I %R", "%I <26>", "<26> %R"},
/* 12	*/	{"fabulous", "exotic", "hoopy", "unusual", "exciting"},
/* 13	*/	{"cuisine", "night life", "casinos", "sit coms", " <32> "},
/* 14	*/	{"%H", "The planet %H", "The world %H", "This planet", "This world"},
/* 15	*/	{"n unremarkable", " boring", " dull", " tedious", " revolting"},
/* 16	*/	{"planet", "world", "place", "little planet", "dump"},
/* 17	*/	{"wasp", "moth", "grub", "ant", "%R"},
/* 18	*/	{"poet", "arts graduate", "yak", "snail", "slug"},
/* 19	*/	{"tropical", "dense", "rain", "impenetrable", "exuberant"},
/* 20	*/	{"funny", "wierd", "unusual", "strange", "peculiar"},
/* 21	*/	{"frequent", "occasional", "unpredictable", "dreadful", "deadly"},
/* 22	*/	{"<1> <0> for <9>", "<1> <0> for <9> and <9>", "<7> by <8>", "<1> <0> for <9> but <7> by <8>"," a<15> <16>"},
/* 23	*/	{"<26>", "mountain", "edible", "tree", "spotted"},
/* 24	*/	{"<30>", "<31>", "<6>oid", "<18>", "<17>"},
/* 25	*/	{"ancient", "exceptional", "eccentric", "ingrained", "<20>"},
/* 26	*/	{"killer", "deadly", "evil", "lethal", "vicious"},
/* 27	*/	{"parking meters", "dust clouds", "ice bergs", "rock formations", "volcanoes"},
/* 28	*/	{"plant", "tulip", "banana", "corn", "%Rweed"},
/* 29	*/	{"%R", "%I %R", "%I <26>", "inhabitant", "%I %R"},
/* 30	*/	{"shrew", "beast", "bison", "snake", "wolf"},
/* 31	*/	{"leopard", "cat", "monkey", "goat", "fish"},
/* 32	*/	{"<11> <10>", "%I <30> <33>","its <12> <31> <33>", "<34> <35>", "<11> <10>"},
/* 33	*/	{"meat", "cutlet", "steak", "burgers", "soup"},
/* 34	*/	{"ice", "mud", "Zero-G", "vacuum", "%I ultra"},
/* 35	*/	{"hockey", "cricket", "karate", "polo", "tennis"}
};


        private string digrams = "ABOUSEITILETSTONLONUTHNOALLEXEGEZACEBISOUSESARMAINDIREA?ERATENBERALAVETIEDORQUANTEISRION";

        private string[] inhabitant_desc1 = {"Large ", "Fierce ", "Small "};

        private string[] inhabitant_desc2 = {"Green ", "Red ", "Yellow ", "Blue ", "Black ", "Harmless "};

        private string[] inhabitant_desc3 = {"Slimy ", "Bug-Eyed ", "Horned ", "Bony ", "Fat ", "Furry "};

        private string[] inhabitant_desc4 = {"Rodent", "Frog", "Lizard", "Lobster", "Bird", "Humanoid", "Feline", "Insect"};
        
        private string sPlanetName = string.Empty;
        
        private string sInhabitants = string.Empty;

        public string Name
        {
            get
            {
                return this.sPlanetName;
            }
        }

        public string Inhabitants
        {
            get
            {
                return this.sInhabitants;
            }
        }

        public planet_data TechData;

        public string Description
        {
            get
            {
                return this.planet_description;
            }
        }

        private galaxy_seed glx;

        public galaxy_seed PlanetGalaxy
        {
            get
            {
                return this.glx;
            }
        }
        #endregion

        /// <summary>
        /// Creates a new planet in galaxy
        /// </summary>
        /// <param name="GalaxyNum">Nuber of galaxy</param>
        /// <param name="PlanetNum">Number planet in that galaxy</param>
        public Planet(galaxy_seed glx)
        {
            this.glx = glx;
            name_planet(glx);
            describe_inhabitants(glx);
            TechData = generate_planet_data(glx);
            describe_planet(glx);
            
        }

        /// <summary>
        /// Generate's Name of planet
        /// </summary>
        private void name_planet(galaxy_seed glx)
        {
            int size;

            if ((glx.a & 0x40) == 0)
                size = 3;
            else
                size = 4;
            
            for (int i = 0; i < size; i++)
            {
                int x = glx.f & 0x1F;
                if (x != 0)
                {
                    x += 12;
                    x *= 2;
                    sPlanetName += digrams[x].ToString();
                    if (digrams[x + 1] != '?')
                        sPlanetName += digrams[x + 1];
                }
                glx = Galaxy.waggle_galaxy(glx);
            }
            sPlanetName=capitalise_name(sPlanetName);
        }

        /// <summary>
        /// Build planet inhabitants
        /// </summary>
        public void describe_inhabitants(galaxy_seed planet)
        {
            int inhab;
            String str;
            str = string.Copy("(");

            if (planet.e < 128)
            {
                str = string.Concat(str, "Human Colonial");
            }
            else
            {
                inhab = (planet.f / 4) & 7;
                if (inhab < 3)
                    str = string.Concat(str, inhabitant_desc1[inhab]);

                inhab = planet.f / 32;
                if (inhab < 6)
                    str = string.Concat(str, inhabitant_desc2[inhab]);

                inhab = (planet.d ^ planet.b) & 7;
                if (inhab < 6)
                    str = string.Concat(str, inhabitant_desc3[inhab]);

                inhab = (inhab + (planet.f & 3)) & 7;
                str = string.Concat(str, inhabitant_desc4[inhab]);
            }

            sInhabitants= string.Concat(str, "s)");
        }

        /// <summary>
        /// Generating planet description
        /// </summary>
        /// <param name="planet_seed">Galaxy</param>
        /// <returns>data as planet_data structure</returns>
        private planet_data generate_planet_data(galaxy_seed planet_seed)
        {
            planet_data pl;

            pl.government = (GovernmentType)((planet_seed.c / 8) & 7);

            pl.economy = (EconomyType)(planet_seed.b & 7);

            if ((int)pl.government < 2)
                pl.economy = (EconomyType)((int)pl.economy | 2);

            pl.techlevel = (int)pl.economy ^ 7;
            pl.techlevel += planet_seed.d & 3;
            pl.techlevel += ((int)pl.government / 2) + ((int)pl.government & 1);


            pl.population = pl.techlevel * 4;
            pl.population += (int)pl.government;
            pl.population += (int)pl.economy;
            pl.population++;

            pl.productivity = ((int)pl.economy ^ 7) + 3;
            pl.productivity *= (int)pl.government + 4;
            pl.productivity *= pl.population;
            pl.productivity *= 8;

            pl.radius = (((planet_seed.f & 15) + 11) * 256) + planet_seed.d;

            return pl;
        }

        private void expand_description(galaxy_seed hyperspace_planet, string source)
        {
            string str = string.Empty;
            int num;
            int rnd=0;
            int option;
            int i, x;
            int iLenght = source.Length;
            
            while (iLenght > 0)
            {
                rnd = gen_rnd_number();

                i = source.IndexOf('<');
                if (i > -1)
                {
                    i += 1;
                    x = source.IndexOf('>');
                    string s = source.Substring(i, x - i);

                    iLenght -= x;

                    num = Convert.ToInt32(s);

                    
                    //if (hoopy_casinos)
                    //{
                    //    option = gen_msx_rnd_number();
                    //}
                    //else
                    {
                        option = 0;
                        if (rnd >= 0x33) option++;
                        if (rnd >= 0x66) option++;
                        if (rnd >= 0x99) option++;
                        if (rnd >= 0xCC) option++;
                      
                    }

                    expand_description(hyperspace_planet, desc_list[num, option]);
                }

                i = source.IndexOf('%');
                if (i > -1)
                {
                    i += 1;
                    iLenght -= i + 1;
                    switch (source.Substring(i, 1))
                    {
                        case "H":
                            source = this.Name;//name_planet(hyperspace_planet);
                            source = capitalise_name(source);
                            //for (ptr = str; *ptr != '\0'; )
                            //    *desc_ptr++ = *ptr++;
                            break;

                        case "I":
                            source = this.Name;// name_planet(hyperspace_planet);
                            source = capitalise_name(source);
                            //            for (ptr = str; *ptr != '\0'; )
                            //                *desc_ptr++ = *ptr++;
                            //            desc_ptr--;
                            source = string.Copy("ian");
                            //            desc_ptr += 3;
                            break;

                        case "R":
                            int len = rnd & 3;
                            for (i = 0; i <= len; i++)
                            {
                                x = rnd & 0x3e;
                                if (i == 0)
                                    planet_description += (digrams[x].ToString());
                                else
                                    planet_description += (digrams[x].ToString());
                                planet_description += (digrams[x + 1].ToString());
                            }
                            break;
                    }

                    //    source++;
                    //continue;
                }
                iLenght--;
                source = source.Substring(source.IndexOf('>') + 1);
                //source = source.Substring(source.IndexOf('%') + 1);
            }

            planet_description += " " + source;
        }

        public string capitalise_name(string sPlanetName)
        {
            string sTemp = sPlanetName.Substring(1).ToLower();
            return sPlanetName[0] + sTemp;
        }

        private int gen_rnd_number()
        {
            int a, x;

            x = (rnd_seed.a * 2) & 0xFF;
            a = x + rnd_seed.c;
            if (rnd_seed.a > 127)
                a++;
            rnd_seed.a = a & 0xFF;
            rnd_seed.c = x;

            a = a / 256;	/* a = any carry left from above */
            x = rnd_seed.b;
            a = (a + x + rnd_seed.d) & 0xFF;
            rnd_seed.b = a;
            rnd_seed.d = x;
            return a;
        }

        private void describe_planet(galaxy_seed planet)
        {
            //string mission_text;
            //if (cmdr.mission == 1)
            //{
            //    mission_text = mission_planet_desc(planet);
            //    if (mission_text != NULL)
            //        return mission_text;
            //}

            rnd_seed.a = planet.c;
            rnd_seed.b = planet.d;
            rnd_seed.c = planet.e;
            rnd_seed.d = planet.f;

            //if (hoopy_casinos)
            //{
            //    rnd_seed.a ^= planet.a;
            //    rnd_seed.b ^= planet.b;
            //    rnd_seed.c ^= rnd_seed.a;
            //    rnd_seed.d ^= rnd_seed.b;
            //}
            expand_description(planet,"<14> is <22> .");
        }
    }
}
